<?php

Raise::load('core.RaiseObject');
Raise::load('core.RaiseString');
Raise::load('core.collection.RaiseCollection');
Raise::load('core.text.regex.RaiseRegex');

/**
 * RaiseOAuthHeader class
 * Define a OAuth header
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @abstract
 * @package phpraise.library.oauth.header
 * @since 1.2
 */
abstract class RaiseOAuthRequest extends RaiseObject{
    
    const KEY_CONSUMER_KEY = 'oauth_consumer_key';
    const KEY_SIGNATURE_METHOD = 'oauth_signature_method';
    const KEY_SIGNATURE = 'oauth_signature';
    const KEY_TIMESTAMP = 'oauth_timestamp';
    const KEY_NONCE = 'oauth_nonce';
    const KEY_VERSION = 'oauth_version';
    
    /**
     *
     * @var string
     */
    private $consumerKey;
    
    /**
     *
     * @var string
     */
    private $signatureMethod;
    
    /**
     *
     * @var string
     */
    private $signature;
    
    /**
     *
     * @var string
     */
    private $timestamp;
    
    /**
     *
     * @var string
     */
    private $nonce;
    
    /**
     *
     * @var string
     */
    private $version;
    
    public function parse($header){
        $a = $this->internalParse($header);
        
        $this->consumerKey = $a->get(RaiseOAuthHeader::KEY_CONSUMER_KEY);
        $this->nonce = $a->get(RaiseOAuthHeader::KEY_NONCE);
        $this->signature = $a->get(RaiseOAuthHeader::KEY_SIGNATURE);
        $this->timestamp = $a->get(RaiseOAuthHeader::KEY_TIMESTAMP);
        $this->signatureMethod = $a->get(RaiseOAuthHeader::KEY_SIGNATURE_METHOD);
        $this->version = $a->get(RaiseOAuthHeader::KEY_VERSION);
    }
    
    public function internalParse($header){
        if(!($header instanceof RaiseString)){
            $header = new RaiseString($header);
        }
        $header = $header->trim();
        $a = new RaiseCollection();
        if($header->substring(0, 5)->toLower() == 'oauth'){
            $header = $header->substring(5)->trim();
            $i = 0;
            $l = $header->length();
            $rgxQuote = new RaiseRegex('`[^\\\\]\"`is');
            while($i < $l){
                $equal = $header->indexOf('=', $i);
                $openingQuote = $rgxQuote->indexOf($header, $i);
                if($openingQuote > -1){
                    $openingQuote++;
                }
                if($equal < $openingQuote && $equal > -1){
                    $key = $header->substring($i, $equal - $i)->trim();
                    $i = $openingQuote + 1;
                    $closingQuote = $rgxQuote->indexOf($header, $i);
                    if($closingQuote > -1){
                        $closingQuote++;
                        $value = $header->substring($i, $closingQuote - $i);
                        $a->add($key->value(), rawurldecode($value->value()));
                        $i = $closingQuote + 1;
                        $comma = $header->indexOf(',', $i);
                        if($comma > -1){
                            $i = $comma + 1;
                        }
                    }else{
                        // TODO: another problem, no closing quote
                        break;
                    }
                }else{
                    // TODO: problem parsing
                    break;
                }
            }
        }
        return $a;
    }
    
    public function request(){
        $s = 'OAuth ';
        $a = new RaiseCollection();
        
        if($this->consumerKey){
            $a->add(RaiseOAuthHeader::KEY_CONSUMER_KEY . '="' . $this->consumerKey . '"');
        }
        
        if($this->nonce){
            $a->add(RaiseOAuthHeader::KEY_NONCE . '="' . $this->nonce . '"');
        }
        
        if($this->signature){
            $a->add(RaiseOAuthHeader::KEY_SIGNATURE . '="' . $this->signature . '"');
        }
        
        if($this->signatureMethod){
            $a->add(RaiseOAuthHeader::KEY_SIGNATURE_METHOD . '="' . $this->signatureMethod . '"');
        }
        
        if($this->timestamp){
            $a->add(RaiseOAuthHeader::KEY_TIMESTAMP . '="' . $this->timestamp . '"');
        }
        
        if($this->version){
            $a->add(RaiseOAuthHeader::KEY_VERSION . '="' . $this->version . '"');
        }
        
        $s .= $a->join(', ');
        return $s;
    }
    
    public function baseSignature(){
        $parts = array(
          $this->get_normalized_http_method(),
          $this->get_normalized_http_url(),
          $this->get_signable_parameters()
        );

        $parts = OAuthUtil::urlencode_rfc3986($parts);

        return implode('&', $parts);
    }
    
    /**
     * Get or set $description$
     * @param string $c (optional) $description$
     * @return string
     */
    public function consumerKey($c = null){
        if(func_num_args() == 1){
            $this->consumerKey = $c;
        }
        return $this->consumerKey;
    }

    /**
     * Get or set $description$
     * @param string $s (optional) $description$
     * @return string
     */
    public function signatureMethod($s = null){
        if(func_num_args() == 1){
            $this->signatureMethod = $s;
        }
        return $this->signatureMethod;
    }

    /**
     * Get or set $description$
     * @param string $s (optional) $description$
     * @return string
     */
    public function signature($s = null){
        if(func_num_args() == 1){
            $this->signature = $s;
        }
        return $this->signature;
    }

    /**
     * Get or set $description$
     * @param string $t (optional) $description$
     * @return string
     */
    public function timestamp($t = null){
        if(func_num_args() == 1){
            $this->timestamp = $t;
        }
        return $this->timestamp;
    }

    /**
     * Get or set $description$
     * @param string $n (optional) $description$
     * @return string
     */
    public function nonce($n = null){
        if(func_num_args() == 1){
            $this->nonce = $n;
        }
        return $this->nonce;
    }

    /**
     * Get or set $description$
     * @param string $v (optional) $description$
     * @return string
     */
    public function version($v = null){
        if(func_num_args() == 1){
            $this->version = $v;
        }
        return $this->version;
    }
    
}